/*
    实现项目中一些琐碎功能
    *日志宏定义
    *json的序列与反序列化
    *uuid的生成
*/
#pragma once
#include <cstdio>
#include <iostream>
#include <string>
#include <ctime>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <chrono>
#include <random>
#include <iomanip>
#include <atomic>


namespace rpc
{
    enum LogLevel
    {
        LDBG = 0,
        LINF,
        LERR
    };
    //默认日志等级
    static int defaultlevel = LINF;

    std::string PrintLevel(int level)
    {
        if(level == LDBG) return "LDBG";
        else if(level == LINF) return "LINF";
        else if(level == LERR) return "LERR";
        else return "";
    }

    //日志
    #define LOG(level, format, ...)  {\
        if(level >= defaultlevel)\
        {\
            time_t t = time(NULL);\
            struct tm* lt = localtime(&t);\
            char time_tmp[32] = {0};\
            strftime(time_tmp, 31, "%m-%d %T", lt);\
            printf("[%s][%s:%d][%s] " format "\n", time_tmp, __FILE__, __LINE__, PrintLevel(level).c_str(),##__VA_ARGS__);\
        }\
    }

    //日志等级
    #define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__)
    #define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__)
    #define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__)


    class JSON
    {
    public:
        static bool serialize(const Json::Value& val, std::string& body)
        {
            std::stringstream ss;
            //先实例化工厂类对象， 再进行派发   
            Json::StreamWriterBuilder swb;
            swb.settings_["emitUTF8"] = true; 
            //newStreamWriter的返回值是StreamWriter*
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(val, &ss);
            if(ret != 0)
            {
                DLOG("streamWrite write fail!");
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool deserialize(const std::string& body, Json::Value& val)
        {
            //实例化工厂类对象
            Json::CharReaderBuilder crb;
            //生产对象
            std::string errs;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            bool ret = cr->parse(body.c_str(), body.c_str()+body.size(), &val, &errs);
            if(!ret){
                ELOG("Json deserialize fail! : %s", errs.c_str());
                return ret;
            }
            return ret;
        }
    };

    class UUID
    {
    public:
        static std::string uuid()
        {
            std::stringstream ss;
            std::random_device rd;
            std::mt19937 genertor (rd());
            std::uniform_int_distribution<int> distribution(0, 255);
            for(int i = 0; i < 8; i++)
            {
                if(i == 4 || i == 6)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(genertor);
            }

            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for(int i = 7; i >= 0; i--)
            {
                if(i == 5)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i*8)) & 0xFF);
            }
            return ss.str();
        }
    };
   
}
